using Minio;
using Minio.DataModel.Args;

namespace GeneralMinioApi.Services
{
    public class MinioService
    {
        private readonly IMinioClient _minioClient;

        private string _bucketName;

        public MinioService(IMinioClient minioClient, IConfiguration config)
        {
            _minioClient = minioClient;
        }

        public async Task EnsureBucketExistsAsync(string bucketName)
        {
            var existsArgs = new BucketExistsArgs().WithBucket(bucketName);
            bool found = await _minioClient.BucketExistsAsync(existsArgs);
            if (!found)
            {
                var makeArgs = new MakeBucketArgs().WithBucket(bucketName);
                await _minioClient.MakeBucketAsync(makeArgs);

                var policyJson = $@"
                    {{
                        ""Version"": ""2012-10-17"",
                        ""Statement"": [
                            {{
                                ""Effect"": ""Allow"",
                                ""Principal"": ""*"",
                                ""Action"": [
                                    ""s3:GetObject"",
                                    ""s3:ListBucket""
                                ],
                                ""Resource"": [
                                    ""arn:aws:s3:::{bucketName}"",
                                    ""arn:aws:s3:::{bucketName}/*""
                                ]
                            }}
                        ]
                    }}";

                await _minioClient.SetPolicyAsync(
                    new SetPolicyArgs()
                    .WithBucket(bucketName)
                    .WithPolicy(policyJson));
            }
        }

        public async Task<Stream> DownloadFileAsync(string bucketName, string objectPath)
        {
            var ms = new MemoryStream();

            var args = new GetObjectArgs()
                .WithBucket(bucketName)
                .WithObject(objectPath)
                .WithCallbackStream(stream =>
                {
                    stream.CopyTo(ms);
                    ms.Position = 0;
                });

            await _minioClient.GetObjectAsync(args);
            return ms;
        }

        /// <summary>
        /// 自动根据文件名后缀归档上传，返回归档路径
        /// </summary>
        public async Task<string> UploadFileAutoTypeAsync(string fileName, Stream fileStream, string bucketName)
        {
            string ext = Path.GetExtension(fileName).TrimStart('.').ToLowerInvariant();
            string fileType = ext;
            string date = DateTime.UtcNow.ToString("yyyyMMdd");
            string nameWithoutExt = Path.GetFileNameWithoutExtension(fileName);
            string unique = DateTime.UtcNow.ToString("yyyyMMddHHmmssfff") + "_" + Guid.NewGuid().ToString("N").Substring(0, 6);
            string newFileName = $"{nameWithoutExt}_{unique}.{ext}";
            string objectName = $"{fileType}/{date}/{newFileName}";
            var putArgs = new PutObjectArgs()
                .WithBucket(bucketName)
                .WithObject(objectName)
                .WithStreamData(fileStream)
                .WithObjectSize(fileStream.Length)
                .WithContentType(GetContentType(fileName));
            await _minioClient.PutObjectAsync(putArgs);
            return objectName;
        }

        /// <summary>
        /// 按完整路径下载文件
        /// </summary>
        public async Task<Stream> DownloadFileByPathAsync(string filePath)
        {
            var ms = new MemoryStream();
            var getArgs = new GetObjectArgs()
                .WithBucket(_bucketName)
                .WithObject(filePath)
                .WithCallbackStream(s => s.CopyTo(ms));
            await _minioClient.GetObjectAsync(getArgs);
            ms.Position = 0;
            return ms;
        }

        private string GetContentType(string fileName)
        {
            var ext = Path.GetExtension(fileName).ToLowerInvariant();
            return ext switch
            {
                ".xlsx" => "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet",
                ".xls" => "application/vnd.ms-excel",
                ".docx" => "application/vnd.openxmlformats-officedocument.wordprocessingml.document",
                ".doc" => "application/msword",
                ".pdf" => "application/pdf",
                ".png" => "image/png",
                ".jpg" => "image/jpeg",
                ".jpeg" => "image/jpeg",
                _ => "application/octet-stream"
            };
        }
    }
}